package com.open.ssm.common.config;

import java.util.List;

import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.open.ssm.common.core.domain.AjaxResult;
import com.open.ssm.common.exception.BaseException;
import com.open.ssm.common.exception.CustomException;
import com.open.ssm.common.utils.StringUtils;
import com.open.ssm.common.utils.bean.BeanValidators;

/**
 * 控制器Controller全局配置
 *
 * @version: v1.0.0
 * @author: wangpf
 * @date: 2022年11月11日 上午11:34:13
 */
@RestControllerAdvice
public class GlobalControllerAdvice {

	protected final Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class);

	@InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class,
                new StringTrimmerEditor(true));
        /*binder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), false));*/
        binder.setDisallowedFields(new String[]{"createBy","createTime","updateBy","updateTime","delFlag"});
    }
	
	/**
     * 基础异常
     */
    @ExceptionHandler(BaseException.class)
    public AjaxResult baseException(BaseException e)
    {
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(CustomException.class)
    public AjaxResult businessException(CustomException e)
    {
        if (StringUtils.isNull(e.getCode()))
        {
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.error(e.getCode(), e.getMessage());
    }
	
	/**
	 * 实体属性校验，ConstraintViolationException异常
	 */
	@ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public AjaxResult handleConstraintViolationException(ConstraintViolationException e) {
		logger.error(e.getMessage(), e);

		List<String> list = BeanValidators.extractPropertyAndMessageAsList(e, ": ");
        return AjaxResult.error(500, "数据验证失败：" + StringUtils.join(list.toArray(), "；"));
    }
	
	/**
     * 自定义验证异常
     * post请求，基于form-data格式的数据传递
     * 配合注解@Validated使用，注解@Validated写在方法参数上，而不能写在类上
     * 例如：public AjaxResult add(@Validated SysUser user){}
     * 
     * jar包：hibernate-validator + validation-api
     */
    @ExceptionHandler(BindException.class)
    public AjaxResult validatedBindException(BindException e) {
    	logger.error(e.getMessage(), e);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return AjaxResult.error(500, "数据验证失败：" + message);
    }
    
    /**
     * 自定义验证异常
     * post请求，基于json格式的数据传递
     * 配合注解@Validated使用，注解@Validated写在方法参数上，而不能写在类上
     * 例如：public AjaxResult add(@Validated @RequestBody SysUser user){}
     * 
     * jar包：hibernate-validator + validation-api
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validExceptionHandler(MethodArgumentNotValidException e)
    {
    	logger.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return AjaxResult.error(message);
    }

}
